iT邦幫忙

2024 iThome 鐵人賽

DAY 21
1
AI/ ML & Data

這跟文件說的不一樣!從 0 到 1 導入 dbt 的實戰甘苦談系列 第 21

DAY 21 Pre-commit 跟文件說的不一樣!談如何透過 pre-commit 提升 SQL 品質

  • 分享至 

  • xImage
  •  

不同人有不同的 coding style,但為了保持整體專案的一致性,我們會建立一些原則,確保大家的程式碼有一定程度的共通性。

SQL 其實有蠻多流派,像是 BigQuery 中,按下快捷鍵 Ctrl + Shift + F 就可以進行格式化,而它是採用所有保留字都全為大寫的風格,換行斷句也有些自己的規則。

image

source: https://www.reddit.com/r/ProgrammerHumor/comments/la0s1m/sql_programmer/

其實早在我發現大小寫不影響執行時,我就懶得用大寫了,看很多影片教學等,發現不少外國人會用大寫寫一整個單字或一段文字,WHICH 我覺得蠻增加我的認知負荷的,都要多一咪咪力氣才能看懂。在 dbt 的文件中,基本上是全小寫的,令人心安。

因為有蠻多不同的規則,雖然有蠻多 extension 可以一鍵排版,但其結果都並非我喜歡的,也不太容易自己做修正。

pre-commit,一套監督大家的程式碼有沒有長一樣的檢查工具,應該有蠻多人介紹過的。

而相較於其他的程式語言,SQL 雖然比較沒有這樣的資源,不過幸好是有 sqlfluff 這個工具可以使用。

(不知道是不是寫 SQL 的人比較沒有在在乎這件事情,還是不會做這件事?)

在部署這個工具的時候,跟想像中有落差的是,在初期需要花力氣去檢視其中的規則。

如方才上述內容,我們有一些規則跟預設的並不相同。

隨便舉一些例子,像是最後一個欄位後是否要有結尾的逗號、group by 可以接受欄位名稱、數字、還是 all?

  • 最後一個欄位後是否要有結尾的逗號(文件說明):

以下是它預設的設定與範例

Anti-pattern

select
    a,
    b,
from foo

Best practice

select
    a,
    b
from foo

但我自己其實傾向使用它視作 anti-pattern 的樣式。因為若當我們要加上一個 c 欄位時,它只要在下方再加上一個 c,、而不是在前一行加上逗號後,在下一行再加上 c。

這個的差別會體現於 PR review 中,一個變動一行、一個變動兩行,但這個變動所做的事情,需要被 review 的其實只是新增的那個欄位,b 是沒有變動的,雖然微小,但積少成多。

SQLfluff 會預設如此,是因為有些資料倉儲中,加上結尾的逗號是 syntax error,只能如此設計。

講到這邊就順便小抱怨一下,BigQuery 在 select 時可以加上句尾逗號,但 group by 與 order by 不行,實在不喜歡不一致的感覺。

  • group by 可以接受欄位名稱、數字、還是 all(文件說明):

Anti-pattern

A mix of implicit and explicit column references are used in a GROUP BY clause.

 SELECT
     foo,
     bar,
     sum(baz) AS sum_value
 FROM fake_table
 GROUP BY
     foo, 2;

Best practice

Reference all GROUP BY/ORDER BY columns either by name or by position.

 -- GROUP BY: Explicit
 SELECT
     foo,
     bar,
     sum(baz) AS sum_value
 FROM fake_table
 GROUP BY
     foo, bar;
 
  -- GROUP BY: Implicit
 SELECT
     foo,
     bar,
     sum(baz) AS sum_value
 FROM fake_table
 GROUP BY
     1, 2;

不知道有沒有人以前沒看過這兩種寫法(現在是都看過了)

我在突然要查一些資訊,這樣一次性的 SQL code 中,絕對是寫數字,有夠方便,不過有人會覺得寫數字太過於抽象,這就看團隊要怎麼找出一個共識。

不過交錯使用(上面的 Anti-pattern)、以及數字是不連續的(e.g. 1,2,3,5,8)應該是普世禁止的。

另外近期 BigQuery 推出了新的語法 group by all(官方文件),它可以直接將 aggregate / window functions 以外的欄位做 grouping,十分方便(懶惰)的新功能。

而這個語法在 SQLfluff 中似乎還沒有支援,因此若要使用這個語法,就必須透過一些旁門左道來避開,像是將所有 group by 的檢查取消掉,或是在該行後面加上後綴以避開檢查。

還有不少其他的案例,在這邊簡單提兩個,文件中規則百百種,任君挑選。

蠻令人慶幸的是,SQLfluff 有支援 dbt 的 templater!(文件

因為 dbt 的 sql file 中,並非純粹的 sql code,有 jinja 語法會混入一些奇怪的語言,如果按照一般的 sql formatter,不只無法將 jinja 部分格式化,還會報錯。

不過這個 templater 也有缺點,這是比較近期才開發的,且功能較多,檢查起來也比較費時費力,文件中都有打一些預防針了,我們現在遇到的問題就是,在本地開發時,時常跑半天跑不出結果,或許應該要遵循官方的建議,改用 jinja templater 看看,之後有空來做這件事情,再跟大家分享。

補充:在撰寫本篇時,發現有人開發了 pre-commit 的 dbt 版本(如文件),名為 dbt-checkpoint,看起來持續在維運中,後續再來試試看是不是更合用。


上一篇
DAY 20 Profiles 跟文件說的不一樣!開發與生產環境的隔離
下一篇
DAY 22 CI/CD 跟文件說的不一樣!用 state 去辨別異動的模型
系列文
這跟文件說的不一樣!從 0 到 1 導入 dbt 的實戰甘苦談30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言